#include "referee.h"
#include "string.h"
#include "stdio.h"
#include "CRC8_CRC16.h"
#include "protocol.h"
#include "NUC_communicate.h"
#include "debug_config.h"
#include "can_receive.h"

frame_header_struct_t referee_receive_header;
frame_header_struct_t referee_send_header;

ext_game_state_t game_state;
ext_game_result_t game_result;
ext_game_robot_HP_t game_robot_HP_t;

ext_event_data_t field_event;
ext_supply_projectile_action_t supply_projectile_action_t;
ext_supply_projectile_booking_t supply_projectile_booking_t;
ext_referee_warning_t referee_warning_t;


ext_game_robot_state_t robot_state; //
ext_power_heat_data_t power_heat_data_t; //
ext_game_robot_pos_t game_robot_pos_t;
ext_buff_musk_t buff_musk_t;
aerial_robot_energy_t robot_energy_t;
ext_robot_hurt_t robot_hurt_t;
ext_shoot_data_t shoot_data_t;
ext_bullet_remaining_t bullet_remaining_t;
ext_student_interactive_data_t student_interactive_data_t;







void init_referee_struct_data(void)
{
    memset(&referee_receive_header, 0, sizeof(frame_header_struct_t));
    memset(&referee_send_header, 0, sizeof(frame_header_struct_t));

    memset(&game_state, 0, sizeof(ext_game_state_t));
    memset(&game_result, 0, sizeof(ext_game_result_t));
    memset(&game_robot_HP_t, 0, sizeof(ext_game_robot_HP_t));


    memset(&field_event, 0, sizeof(ext_event_data_t));
    memset(&supply_projectile_action_t, 0, sizeof(ext_supply_projectile_action_t));
    memset(&supply_projectile_booking_t, 0, sizeof(ext_supply_projectile_booking_t));
    memset(&referee_warning_t, 0, sizeof(ext_referee_warning_t));


    memset(&robot_state, 0, sizeof(ext_game_robot_state_t));
    memset(&power_heat_data_t, 0, sizeof(ext_power_heat_data_t));
    memset(&game_robot_pos_t, 0, sizeof(ext_game_robot_pos_t));
    memset(&buff_musk_t, 0, sizeof(ext_buff_musk_t));
    memset(&robot_energy_t, 0, sizeof(aerial_robot_energy_t));
    memset(&robot_hurt_t, 0, sizeof(ext_robot_hurt_t));
    memset(&shoot_data_t, 0, sizeof(ext_shoot_data_t));
    memset(&bullet_remaining_t, 0, sizeof(ext_bullet_remaining_t));
    memset(&student_interactive_data_t, 0, sizeof(ext_student_interactive_data_t));


}

void referee_data_solve(uint8_t *frame)
{
    uint16_t cmd_id = 0;

    uint8_t index = 0;

    memcpy(&referee_receive_header, frame, sizeof(frame_header_struct_t));

    index += sizeof(frame_header_struct_t);

    memcpy(&cmd_id, frame + index, sizeof(uint16_t));
    index += sizeof(uint16_t);

    switch (cmd_id)
    {
        case GAME_STATE_CMD_ID:
        {
            memcpy(&game_state, frame + index, sizeof(ext_game_state_t));
        }
        break;
        case GAME_RESULT_CMD_ID:
        {
            memcpy(&game_result, frame + index, sizeof(game_result));
        }
        break;
        case GAME_ROBOT_HP_CMD_ID:
        {
            memcpy(&game_robot_HP_t, frame + index, sizeof(ext_game_robot_HP_t));
        }
        break;


        case FIELD_EVENTS_CMD_ID:
        {
            memcpy(&field_event, frame + index, sizeof(field_event));
        }
        break;
        case SUPPLY_PROJECTILE_ACTION_CMD_ID:
        {
            memcpy(&supply_projectile_action_t, frame + index, sizeof(supply_projectile_action_t));
        }
        break;
        case SUPPLY_PROJECTILE_BOOKING_CMD_ID:
        {
            memcpy(&supply_projectile_booking_t, frame + index, sizeof(supply_projectile_booking_t));
        }
        break;
        case REFEREE_WARNING_CMD_ID:
        {
            memcpy(&referee_warning_t, frame + index, sizeof(ext_referee_warning_t));
        }
        break;

        case ROBOT_STATE_CMD_ID:
        {
            memcpy(&robot_state, frame + index, sizeof(robot_state));
        }
        break;
        case POWER_HEAT_DATA_CMD_ID:
        {
            memcpy(&power_heat_data_t, frame + index, sizeof(power_heat_data_t));
        }
        break;
        case ROBOT_POS_CMD_ID:
        {
            memcpy(&game_robot_pos_t, frame + index, sizeof(game_robot_pos_t));
        }
        break;
        case BUFF_MUSK_CMD_ID:
        {
            memcpy(&buff_musk_t, frame + index, sizeof(buff_musk_t));
        }
        break;
        case AERIAL_ROBOT_ENERGY_CMD_ID:
        {
            memcpy(&robot_energy_t, frame + index, sizeof(robot_energy_t));
        }
        break;
        case ROBOT_HURT_CMD_ID:
        {
            memcpy(&robot_hurt_t, frame + index, sizeof(robot_hurt_t));
        }
        break;
        case SHOOT_DATA_CMD_ID:
        {
            memcpy(&shoot_data_t, frame + index, sizeof(shoot_data_t));
        }
        break;
        case BULLET_REMAINING_CMD_ID:
        {
            memcpy(&bullet_remaining_t, frame + index, sizeof(ext_bullet_remaining_t));
        }
        break;
        case STUDENT_INTERACTIVE_DATA_CMD_ID:
        {
            memcpy(&student_interactive_data_t, frame + index, sizeof(student_interactive_data_t));
        }
        break;
        default:
        {
            break;
        }
    }
}

void get_chassis_power_and_buffer(fp32 *power, fp32 *buffer)
{
    *power = power_heat_data_t.chassis_power;
    *buffer = power_heat_data_t.buffer_energy;

}

void get_power_limit(uint16_t *powerLimit){
    *powerLimit=robot_state.chassis_power_limit;
}


void get_shoot_heat_limit_and_heat_infantry(uint16_t *heat_limit, uint16_t *heat)
{
    *heat_limit = robot_state.shooter_barrel_heat_limit;
    *heat = power_heat_data_t.shooter_17mm_1_barrel_heat;
}

void get_shoot_heat_limit_and_heat_hero(uint16_t *heat_limit, uint16_t *heat)
{
    *heat_limit = robot_state.shooter_barrel_heat_limit;
    *heat = power_heat_data_t.shooter_42mm_barrel_heat;
}


void get_shoot_heat_limit_and_heat_sentry_1(uint16_t *heat_limit, uint16_t *heat)
{
    *heat_limit = robot_state.shooter_barrel_heat_limit;
    *heat = power_heat_data_t.shooter_17mm_1_barrel_heat;
}

void get_shoot_heat_limit_and_heat_sentry_2(uint16_t *heat_limit, uint16_t *heat)
{
    *heat_limit = robot_state.shooter_barrel_heat_limit;
    *heat = power_heat_data_t.shooter_17mm_2_barrel_heat;
}

uint8_t get_robot_id(void)
{
    return robot_state.robot_id;
}
int game_not_started(void)
{
    return (game_state.game_progress < PROGRESS_BATTLE);
}
#ifdef SENTRY_CHASSIS
uint8_t get_power_LIMITE(void){
    return (uint8_t)robot_state.chassis_power_limit;
}

uint8_t get_power(void){
    return (uint8_t)power_heat_data_t.chassis_power;
}

uint8_t get_buff(void){
    return (uint8_t)power_heat_data_t.buffer_energy;
}

uint16_t get_shoot_heat_limit(void){
    return robot_state.shooter_barrel_heat_limit;
}

uint16_t get_shoot_heat_1(void){
    return power_heat_data_t.shooter_17mm_1_barrel_heat;
}

uint16_t get_shoot_heat_2(void){
    return power_heat_data_t.shooter_17mm_2_barrel_heat;
}

#endif


#ifdef USE_USART
#ifndef TEST_USART
#define COLOR_BLUE 'B'
#define COLOR_RED  'R'
void get_toNUCData(toNUC_t *toNUCData)
{
    uint8_t j;
    uint8_t* p = (uint8_t*)toNUCData;
    toNUCData->start = 'S';
    toNUCData->blood = robot_state.current_HP;
    toNUCData->bullet_remaining = bullet_remaining_t.bullet_remaining_num;
    toNUCData->my_color = (robot_state.robot_id > 100) ? COLOR_BLUE : COLOR_RED;
    toNUCData->checksum = 0;
    for (j = 1; j < sizeof(toNUC_t)-2; j++)
        toNUCData->checksum += p[j];
    toNUCData->end = 'E';
}
#endif
#endif

#ifdef USE_CAN
#define COLOR_BLUE 0x80
#define COLOR_RED  0x00
void get_toNUCData(uint8_t * sendToNuc)
{
    sendToNuc[0]=0;
    sendToNuc[0] += (robot_state.robot_id > 100) ? COLOR_BLUE : COLOR_RED;
    sendToNuc[0] += (game_state.game_progress<<4)&(0x70);
    if(robot_state.robot_id > 100){
        sendToNuc[0] += ((game_robot_HP_t.blue_1_robot_HP+game_robot_HP_t.blue_2_robot_HP+game_robot_HP_t.blue_3_robot_HP+game_robot_HP_t.blue_4_robot_HP+game_robot_HP_t.blue_5_robot_HP+game_robot_HP_t.blue_7_robot_HP+game_robot_HP_t.blue_base_HP)>(game_robot_HP_t.red_1_robot_HP+game_robot_HP_t.red_2_robot_HP+game_robot_HP_t.red_3_robot_HP+game_robot_HP_t.red_4_robot_HP+game_robot_HP_t.red_5_robot_HP+game_robot_HP_t.red_7_robot_HP+game_robot_HP_t.red_base_HP)? 1:0)<<2;
    }else{
        sendToNuc[0] += ((game_robot_HP_t.blue_1_robot_HP+game_robot_HP_t.blue_2_robot_HP+game_robot_HP_t.blue_3_robot_HP+game_robot_HP_t.blue_4_robot_HP+game_robot_HP_t.blue_5_robot_HP+game_robot_HP_t.blue_7_robot_HP+game_robot_HP_t.blue_base_HP)>(game_robot_HP_t.red_1_robot_HP+game_robot_HP_t.red_2_robot_HP+game_robot_HP_t.red_3_robot_HP+game_robot_HP_t.red_4_robot_HP+game_robot_HP_t.red_5_robot_HP+game_robot_HP_t.red_7_robot_HP+game_robot_HP_t.red_base_HP)? 0:1)<<2;
    }
    sendToNuc[0] += (game_state.stage_remain_time>=(1<<8))? 1:0;
    sendToNuc[1] =  game_state.stage_remain_time;
}
#endif
